﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Caching;
using System.Xml.Linq;
using EPiServer;
using Hosting.FlickrObjects;

namespace Hosting
{
    /*
     * TODO: figure out a better way to deal with the serviceUrl parameter...
     * */
    public class FlickrDataFactory
    {
        static FlickrDataFactory _instance = new FlickrDataFactory();

        FlickrDataFactory()
        {
            
        }

        public static FlickrDataFactory Instance
        {
            get
            {
                return _instance;
            }
        }

        public List<Photo> GetPhotos(string serviceUrl, string photoSetId)
        {
            var args = new NameValueCollection
                           {
                               {"photoset_id", photoSetId}
                           };

            var doc = GetApiResponse(serviceUrl, "flickr.photosets.getPhotos", args);

            var photos = doc.Descendants("photo").Select(set => new Photo
                                                                    {
                                                                        ID = set.Attribute("id").Value,
                                                                        Title = set.Attribute("title").Value + ".jpg",
                                                                        Secret = set.Attribute("secret").Value,
                                                                        Server = set.Attribute("server").Value,
                                                                        Farm = set.Attribute("farm").Value
                                                                    });
            return photos.ToList();
        }

        public List<PhotoSet> GetPhotoSets(string serviceUrl)
        {
            var doc = GetApiResponse(serviceUrl, "flickr.photosets.getList");

            var photoset = doc.Descendants("photoset").Select(set => new PhotoSet
                                                                         {
                                                                             ID = set.Attribute("id").Value,
                                                                             Title = set.Element("title").Value,
                                                                             Description =
                                                                                 set.Element("description").Value
                                                                         });
            return photoset.ToList();
        }

        private static XDocument GetApiResponse(string serviceUrl, string method, NameValueCollection param = null)
        {
            if(param == null)
            {
                param = new NameValueCollection();
            }

            // UrlDecode because it's encoded in the config file.. or else the xml won't validate
            var baseUrl = String.Format(HttpUtility.UrlDecode(serviceUrl), method);

            Debug.WriteLine("GetApiResponse(" + serviceUrl + ")");

            // HACK: do this better..
            baseUrl = param.AllKeys.Aggregate(baseUrl, (current, p) => current + ("&" + p + "=" + param[p]));

            // get xml from cache
            var cacheKey = "FlickrVPP_" + baseUrl;
            var doc = (XDocument) CacheManager.Get(cacheKey);
            if(doc != null)
            {
                return doc;
            }

            // not cached. Get it from Flickr
            var req = (HttpWebRequest)WebRequest.Create(baseUrl);

            using (var stream = new StreamReader(req.GetResponse().GetResponseStream()))
            {
                var xml = stream.ReadToEnd();
                stream.Close();

                doc = XDocument.Parse(xml);

                // TODO: make cache time configurable
                CacheManager.RuntimeCacheAdd(cacheKey, doc, null, DateTime.Now.AddSeconds(30), Cache.NoSlidingExpiration);
                return doc;
            }
        }

        public void DownloadPhoto(Photo photo, string localPath)
        {
            var client = new WebClient();
            client.DownloadFile(photo.ToUrl(), localPath);
        }

        public void UploadPhoto(string name, byte[] content)
        {
            throw new NotImplementedException("Uploading photos is not implemented.");
        }
    }
}
